<template>
  <view class="tree-view">
    <!-- 工具栏 -->
    <view class="tree-toolbar">
      <view class="tool-group">
        <view class="tool-btn" @tap="handleExpandAll">
          <uni-icons :type="isExpandAll ? 'minus' : 'plus'" size="12" color="#409eff"></uni-icons>
          <text>{{ isExpandAll ? '收起' : '展开' }}</text>
        </view>
        <view class="tool-btn" @tap="toggleStrictly">
          <uni-icons :type="checkStrictly ? 'checkbox-filled' : 'circle'" size="12" color="#409eff"></uni-icons>
          <text>联动</text>
        </view>
        <view class="tool-btn" @tap="handleSelectAll">
          <uni-icons
            :type="isAllSelected ? 'checkbox-filled' : 'square'"
            size="12"
            :color="isAllSelected ? '#409eff' : '#dcdfe6'"
          ></uni-icons>
          <text>全选</text>
        </view>
        <view class="tool-btn" @tap="handleInvertSelect">
          <uni-icons type="reload" size="12" color="#409eff"></uni-icons>
          <text>反选</text>
        </view>
      </view>
    </view>

    <!-- 树形内容 -->
    <view class="tree-content">
      <template v-if="!data || data.length === 0">
        <view class="empty-tip">暂无数据</view>
      </template>
      <template v-else>
        <xlam-tree-node
          v-for="node in data"
          :key="node.id"
          :node="node"
          :selected="selected"
          :expanded="expandedNodes"
          :checkStrictly="checkStrictly"
          @select="handleSelect"
          @toggle="handleToggle"
        />
      </template>
    </view>
  </view>
</template>

<script>
import XlamTreeNode from './node.vue'

export default {
  name: 'xlam-tree',
  components: {
    XlamTreeNode
  },
  props: {
    data: {
      type: Array,
      default: () => []
    },
    value: {
      type: Array,
      default: () => []
    },
    defaultStrictly: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      selected: this.value,
      expandedNodes: new Set(),
      isExpandAll: false,
      checkStrictly: false
    }
  },
  watch: {
    value: {
      handler(val) {
        this.selected = val
      },
      deep: true
    },
    defaultStrictly: {
      handler(val) {
        this.checkStrictly = val
      },
      immediate: true
    }
  },
  computed: {
    // 添加计算属性判断是否全部选中
    isAllSelected() {
      const allIds = this.getAllSelectableIds()
      return allIds.length > 0 && allIds.every(id => this.selected.includes(id))
    }
  },
  methods: {
    // 处理节点选择
    handleSelect(event) {
      const { id, type, children } = event
      let newSelected = [...this.selected]

      if (this.checkStrictly) {
        // 父子联动模式
        if (type === 'select') {
          // 选中节点和所有子节点
          const toAdd = [id, ...children].filter(i => !newSelected.includes(i))
          newSelected.push(...toAdd)
          // 检查父节点
          this.checkParentNodes(this.data, id, newSelected)
        } else {
          // 取消选中节点和所有子节点
          newSelected = newSelected.filter(i => ![id, ...children].includes(i))
          // 检查父节点
          this.uncheckParentNodes(this.data, id, newSelected)
        }
      } else {
        // 非联动模式
        if (type === 'select') {
          newSelected.push(id)
        } else {
          newSelected = newSelected.filter(i => i !== id)
        }
      }

      this.selected = newSelected
      this.$emit('input', newSelected)
      this.$emit('change', newSelected)
    },

    // 处理节点展开/收起
    handleToggle(nodeId) {
      if (this.expandedNodes.has(nodeId)) {
        this.expandedNodes.delete(nodeId)
      } else {
        this.expandedNodes.add(nodeId)
      }
    },

    // 全部展开/收起
    handleExpandAll() {
      if (this.isExpandAll) {
        this.expandedNodes.clear()
      } else {
        this.getAllNodeIds(this.data).forEach(id => {
          this.expandedNodes.add(id)
        })
      }
      this.isExpandAll = !this.isExpandAll
    },

    // 切换父子联动
    toggleStrictly() {
      this.checkStrictly = !this.checkStrictly
      this.$emit('update:defaultStrictly', this.checkStrictly)
    },

    // 获取所有节点ID
    getAllNodeIds(nodes) {
      const ids = []
      const getIds = (nodes) => {
        nodes.forEach(node => {
          ids.push(node.id)
          if (node.children) {
            getIds(node.children)
          }
        })
      }
      getIds(nodes)
      return ids
    },

    // 检查并选中父节点
    checkParentNodes(nodes, childId, selectedIds, parentId = null) {
      for (const node of nodes) {
        if (node.id === childId && parentId) {
          const parent = this.findNodeById(this.data, parentId)
          if (parent && parent.children.every(child => selectedIds.includes(child.id))) {
            if (!selectedIds.includes(parentId)) {
              selectedIds.push(parentId)
              this.checkParentNodes(this.data, parentId, selectedIds)
            }
          }
          return
        }
        if (node.children) {
          this.checkParentNodes(node.children, childId, selectedIds, node.id)
        }
      }
    },

    // 检查并取消选中父节点
    uncheckParentNodes(nodes, childId, selectedIds, parentId = null) {
      for (const node of nodes) {
        if (node.id === childId && parentId) {
          const index = selectedIds.indexOf(parentId)
          if (index > -1) {
            selectedIds.splice(index, 1)
            this.uncheckParentNodes(this.data, parentId, selectedIds)
          }
          return
        }
        if (node.children) {
          this.uncheckParentNodes(node.children, childId, selectedIds, node.id)
        }
      }
    },

    // 根据ID查找节点
    findNodeById(nodes, id) {
      for (const node of nodes) {
        if (node.id === id) return node
        if (node.children) {
          const found = this.findNodeById(node.children, id)
          if (found) return found
        }
      }
      return null
    },

    // 获取所有可选节点ID
    getAllSelectableIds(nodes = this.data) {
      const ids = []
      const getIds = (nodes) => {
        nodes.forEach(node => {
          ids.push(node.id)
          if (node.children) {
            getIds(node.children)
          }
        })
      }
      getIds(nodes)
      return ids
    },

    // 全选
    handleSelectAll() {
      const allIds = this.getAllSelectableIds()
      if (this.isAllSelected) {
        // 如果已全选，则取消全选
        this.selected = []
      } else {
        // 如果未全选，则全选
        this.selected = allIds
      }
      this.$emit('input', this.selected)
      this.$emit('change', this.selected)
    },

    // 反选
    handleInvertSelect() {
      const allIds = this.getAllSelectableIds()
      const invertedIds = allIds.filter(id => !this.selected.includes(id))
      this.selected = invertedIds
      this.$emit('input', invertedIds)
      this.$emit('change', invertedIds)
    }
  }
}
</script>

<style lang="scss">
.tree-view {
  background-color: #fff;
  border-radius: 12rpx;

  .tree-toolbar {
    padding: 16rpx 20rpx;
    border-bottom: 1rpx solid #f0f2f5;

    .tool-group {
      display: flex;
      gap: 16rpx;
      flex-wrap: wrap;

      .tool-btn {
        display: flex;
        align-items: center;
        padding: 8rpx 16rpx;
        font-size: 24rpx;
        color: #409eff;
        background-color: #ecf5ff;
        border-radius: 6rpx;
        transition: all 0.3s;
        margin-bottom: 8rpx;

        &:active {
          opacity: 0.8;
          transform: scale(0.98);
        }

        text {
          margin-left: 6rpx;
        }
      }
    }
  }

  .tree-content {
    padding: 20rpx;
    max-height: 600rpx;
    overflow-y: auto;
  }

  .empty-tip {
    text-align: center;
    color: #909399;
    font-size: 28rpx;
    padding: 40rpx 0;
  }
}
</style>